package com.javawork.juc.two;

/**
 * @author zhangxiaolu
 * @date 2023-02-06 23:16
 */
public class SynchronizedTestDemo2 {

    /**
     * 上面代码中countAdd是一个synchronized的，printCount是非synchronized的。从上面的结果中可以看出一个线程访问一个对象的synchronized代码块时，别的线程可以访问该对象的非synchronized代码块而不受阻塞。
     *
     * @param args
     */
    public static void main(String[] args) {
        System.out.println("使用关键字synchronized");
        Mythreads mt = new Mythreads();
        Thread thread1 = new Thread(mt, "mt1");
        Thread thread2 = new Thread(mt, "mt2");
        thread1.start();
        thread2.start();
    }
}

class Mythreads implements Runnable {
    private int count;

    public Mythreads() {
        count = 0;
    }

    public void countAdd() {
        synchronized (this) {
            for (int i = 0; i < 5; i++) {
                try {
                    System.out.println(Thread.currentThread().getName() + ":" + (count++));
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    //非synchronized代码块，未对count进行读写操作，所以可以不用synchronized
    public void printCount() {
        for (int i = 0; i < 5; i++) {
            try {
                System.out.println(Thread.currentThread().getName() + " count:" + count);
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    //    public void run() {
//        String threadName = Thread.currentThread().getName();
//        if (threadName.equals("mt1")) {
//            countAdd();
//        } else if (threadName.equals("mt2")) {
//            printCount();
//        }
//    }

    /**
     * Synchronized修饰一个方法很简单，就是在方法的前面加synchronized，public synchronized void method(){};
     * synchronized修饰方法和修饰一个代码块类似，只是作用范围不一样，修饰代码块是大括号括起来的范围，而修饰方法范围是整个函数。
     * 如将的run方法改成如下的方式，实现的效果一样。
     */
    public synchronized void run() {
        {
            for (int i = 0; i < 5; i++) {
                try {
                    System.out.println("线程名:" + Thread.currentThread().getName() + ":" + (count++));
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}